/*
 * @Author: xiaosihan 
 * @Date: 2021-06-06 23:48:53 
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2021-06-13 14:44:05
 */

import React from "react";
import * as THREE from 'three';
import { ShaderMaterial } from "three";
import { ClipPlane, Group3D, Mesh, MeshMaterialType, Text3D, TextAlign, THREEComponent } from "xsh-react-three";
import { Vector3 } from "xsh-react-three/lib/Object3D/type";
import { THREEMouseEvent } from "xsh-react-three/lib/Renderer/THREEMouse";

export type Bar3DData = {
    value: number,
    [key: string]: any
}

interface Bar3DProps {
    datas: Bar3DData[];
    width?: number;
    height?: number;
    material?: MeshMaterialType | ShaderMaterial;
    color?: string;

    title?: (data: any) => React.Component | String;

    position?: Vector3;
    rotation?: Vector3;
    scale?: Vector3;

    // 鼠标相关
    cursor?: string;//-----------------------------鼠标样式
    onMousemove?: (e: THREEMouseEvent) => void;//--鼠标滑动事件
    onMouseleave?: (e: THREEMouseEvent) => void;//-鼠标离开事件
    onMouseenter?: (e: THREEMouseEvent) => void;//-鼠标进入事件
    onMousedown?: (e: THREEMouseEvent) => void;//--鼠标按下事件
    onMouseup?: (e: THREEMouseEvent) => void;//----鼠标弹起事件
    onClick?: (e: THREEMouseEvent) => void;//------鼠标点击事件
}

interface State { }

export default class Bar3D extends THREEComponent<Bar3DProps, State> {
    constructor(props: Bar3DProps) {
        super(props);
    }

    static defaultProps = {
        datas: [1],
        width: 10,
        height: 10,
        material: MeshMaterialType.MeshNormalMaterial
    }

    static boxGeo = new THREE.BoxBufferGeometry(1, 1, 1, 1, 1, 1);

    render() {

        const {
            datas,
            width = 10,
            height = 10,
            material,
            color,
            title,

            position,
            rotation,
            scale,

            // 鼠标相关
            cursor,
            onMousemove,
            onMouseleave,
            onMouseenter,
            onMousedown,
            onMouseup,
            onClick
        } = this.props;

        let widthScale = width / ((datas.length - 0.5) * 2);

        let maxValue = Math.max(...datas.map(d => d.value));

        return (
            <Group3D
                position={position}
                rotation={rotation}
                scale={scale}
            >

                <Group3D
                    name="Bar3D"
                    scale={{ x: widthScale, z: widthScale }}
                >
                    {
                        datas.map((data, index) => {
                            return (
                                <Group3D
                                    key={index}
                                    position={{ x: index * 2 }}
                                >
                                    <Mesh
                                        geometry={Bar3D.boxGeo}
                                        position={{ y: data.value / 2 / (maxValue / height) }}
                                        scale={{ y: data.value / (maxValue / height) }}
                                        material={material}
                                        color={color}
                                        cursor={cursor}

                                        title={
                                            <span
                                                style={{
                                                    position: "relative",
                                                    backgroundColor: "rgba(0, 0, 0, 0.8)",
                                                    borderRadius: 4,
                                                    padding: "4px 8px",
                                                    color: "#fff"
                                                }}
                                            >
                                                {title ? title(datas[index]) : `value:${datas[index].value}`}
                                            </span>
                                        }

                                        onMousemove={onMousemove ? e => onMousemove(Object.assign(e, { data: datas[index], index })) : undefined}
                                        onMouseleave={onMouseleave ? e => onMouseleave(Object.assign(e, { data: datas[index], index })) : undefined}
                                        onMouseenter={onMouseenter ? e => onMouseenter(Object.assign(e, { data: datas[index], index })) : undefined}
                                        onMousedown={onMousedown ? e => onMousedown(Object.assign(e, { data: datas[index], index })) : undefined}
                                        onMouseup={onMouseup ? e => onMouseup(Object.assign(e, { data: datas[index], index })) : undefined}
                                        onClick={onClick ? e => onClick(Object.assign(e, { data: datas[index], index })) : undefined}

                                    />

                                    <Text3D
                                        size={1}
                                        scale={{ z: 0.2, y: widthScale }}
                                        height={0.01}
                                        bevelSize={0.01}
                                        text={String(data.value)}
                                        position={{ x: 0.5, y: (data.value / (maxValue / height)) + widthScale }}
                                        textAlign={TextAlign.CENTER_CENTER}
                                        material={MeshMaterialType.MeshNormalMaterial}
                                    />

                                </Group3D>
                            );
                        })
                    }

                </Group3D>

                <ClipPlane
                    position={{ x: width + 0.05 }}
                    rotation={{ y: -90 }}
                />

            </Group3D>
        );
    }
}


Bar3D.boxGeo.translate(0.5, 0, 0);
